﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Media.Animation;

namespace GraphGenericTestApp
{
    /// <summary>
    /// Interaction logic for GraphViewer.xaml
    /// </summary>
    public partial class GraphViewerOld : UserControl
    {
        public GraphViewerOld()
        {
            InitializeComponent();
            Zoom = 1;
        }



        public Point ScrollPosition
        {
            get { return (Point)GetValue(ScrollPositionProperty); }
            set { SetValue(ScrollPositionProperty, value); }
        }

        // Using a DependencyProperty as the backing store for ScrollPosition.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ScrollPositionProperty =
            DependencyProperty.Register("ScrollPosition", typeof(Point), typeof(GraphViewerOld), new UIPropertyMetadata(new Point(0, 0), new PropertyChangedCallback(OnScrollPositionChanged)));

        private static void OnScrollPositionChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
        {
            GraphViewerOld viewer = sender as GraphViewerOld;
            viewer.MainScrollViewer.ScrollToHorizontalOffset((viewer.MainGrid.Width - viewer.MainScrollViewer.ViewportWidth) * viewer.ScrollPosition.X);
            viewer.MainScrollViewer.ScrollToVerticalOffset((viewer.MainGrid.Height - viewer.MainScrollViewer.ViewportHeight) * viewer.ScrollPosition.Y);
        }

        #region Properties

        public double Zoom
        {
            get { return m_zoom; }
            set
            {
                if (m_zoom != value)
                {
                    m_zoom = value;
                    GraphCanvas.Scale = value;
                }
            }
        }

        #endregion

        public void RepositionNodes()
        {
            GraphCanvas.SetNodeLocatations();
        }
        public void DrawEdges()
        {
            GraphCanvas.DrawEdges();
        }

        protected override void OnPreviewMouseLeftButtonDown(MouseButtonEventArgs e)
        {
            if (MainScrollViewer.IsMouseOver)
            {
                m_startScrollPoint = e.GetPosition(this);
                m_startScrollOffset.X = MainScrollViewer.HorizontalOffset;
                m_startScrollOffset.Y = MainScrollViewer.VerticalOffset;

                Cursor = Cursors.ScrollAll;
                CaptureMouse();
            }

            base.OnPreviewMouseLeftButtonDown(e);
        }
        protected override void OnPreviewMouseLeftButtonUp(MouseButtonEventArgs e)
        {
            if (IsMouseCaptured)
            {
                Cursor = Cursors.Arrow;
                CenterScrollViewer(true);
                ReleaseMouseCapture();
            }
            base.OnPreviewMouseLeftButtonUp(e);
        }
        protected override void OnPreviewMouseMove(MouseEventArgs e)
        {
            if (IsMouseCaptured)
            {
                Point newPoint = e.GetPosition(this);

                double dx = newPoint.X > m_startScrollPoint.X ? -(newPoint.X - m_startScrollPoint.X) : m_startScrollPoint.X - newPoint.X;
                double dy = newPoint.Y > m_startScrollPoint.Y ? -(newPoint.Y - m_startScrollPoint.Y) : m_startScrollPoint.Y - newPoint.Y;

                MainScrollViewer.ScrollToHorizontalOffset(m_startScrollOffset.X + dx);
                MainScrollViewer.ScrollToVerticalOffset(m_startScrollOffset.Y + dy);
            }
            base.OnPreviewMouseMove(e);
        }



        #region Event Handlers

        protected override void OnInitialized(EventArgs e)
        {
            MainScrollViewer.SizeChanged += new SizeChangedEventHandler(MainScrollViewer_SizeChanged);
            MainScrollViewer.Loaded += new RoutedEventHandler(MainScrollViewer_Loaded);
            MainGrid.SizeChanged += new SizeChangedEventHandler(MainGrid_SizeChanged);
            GraphCanvas.Loaded += new RoutedEventHandler(GraphCanvas_Loaded);
            base.OnInitialized(e);
        }
        
        void MainGrid_SizeChanged(object sender, SizeChangedEventArgs e)
        {

        }



        void MainScrollViewer_Loaded(object sender, RoutedEventArgs e)
        {
            MainGrid.Width = MainScrollViewer.ViewportWidth * 2;
            MainGrid.Height = MainScrollViewer.ViewportHeight * 2;
            CenterScrollViewer(false);
        }


        private void GraphCanvas_Loaded(object sender, RoutedEventArgs e)
        {
            GraphCanvas.SetNodeLocatations();
        }

        private void MainScrollViewer_MouseDown(object sender, MouseButtonEventArgs e)
        {
            if (e.ChangedButton == MouseButton.XButton2)
                Zoom += .1;
            else if (e.ChangedButton == MouseButton.XButton1)
                Zoom -= .1;

        }
        private void MainScrollViewer_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            CenterScrollViewer(false);
        }

        #endregion

        private void CenterScrollViewer(bool animate)
        {
            if (MainScrollViewer.ViewportWidth > 0 && MainScrollViewer.ViewportHeight > 0)
            {
                MainGrid.Width = MainScrollViewer.ViewportWidth * 2;
                MainGrid.Height = MainScrollViewer.ViewportHeight * 2;
                if (animate)
                {
                    PointAnimation anim = new PointAnimation();
                    anim.Duration = new Duration(TimeSpan.FromSeconds(.5));
                    anim.AccelerationRatio = 0.5;
                    anim.DecelerationRatio = 0.5;
                    anim.From = new Point(
                       MainScrollViewer.HorizontalOffset / MainScrollViewer.ViewportWidth,
                       MainScrollViewer.VerticalOffset / MainScrollViewer.ViewportHeight);
                    anim.To = new Point(0.5, 0.5);
                    BeginAnimation(ScrollPositionProperty, anim);
                }
                else
                {
                    ScrollPosition = new Point(0.5, 0.5);
                    OnScrollPositionChanged(this, new DependencyPropertyChangedEventArgs());
                }
            }
        }


        #region Fields

        private double m_zoom;
        private Point m_startScrollPoint;
        private Point m_startScrollOffset;

        #endregion
    }
}
